//因为Hspi总线被lvgl的屏幕刷新回调占用而ESP32S3又只有HSPI可用，目前暂未解决运行lvgl时怎么使用sd卡，但是可以播放网络的歌曲
#include"AXS15231B.h"
#include<lvgl.h>
#include <Arduino.h>
#include <Wire.h>
#include "ui.h"

#include "music_sd.h"
#include "pincfg.h"//引脚定义
#include <Ticker.h>//定时器
// 定义定时器对象
Ticker timer;//定时器





uint8_t ALS_ADDRESS = 0x3B;
#define TOUCH_IICSCL TOUCH_PIN_NUM_I2C_SCL
#define TOUCH_IICSDA TOUCH_PIN_NUM_I2C_SDA
#define TOUCH_INT TOUCH_PIN_NUM_INT
#define TOUCH_RES TOUCH_PIN_NUM_RST

#define AXS_TOUCH_ONE_POINT_LEN             6
#define AXS_TOUCH_BUF_HEAD_LEN              2

#define AXS_TOUCH_GESTURE_POS               0
#define AXS_TOUCH_POINT_NUM                 1
#define AXS_TOUCH_EVENT_POS                 2
#define AXS_TOUCH_X_H_POS                   2
#define AXS_TOUCH_X_L_POS                   3
#define AXS_TOUCH_ID_POS                    4
#define AXS_TOUCH_Y_H_POS                   4
#define AXS_TOUCH_Y_L_POS                   5
#define AXS_TOUCH_WEIGHT_POS                6
#define AXS_TOUCH_AREA_POS                  7

#define AXS_GET_POINT_NUM(buf) buf[AXS_TOUCH_POINT_NUM]
#define AXS_GET_GESTURE_TYPE(buf)  buf[AXS_TOUCH_GESTURE_POS]
#define AXS_GET_POINT_X(buf,point_index) (((uint16_t)(buf[AXS_TOUCH_ONE_POINT_LEN*point_index+AXS_TOUCH_X_H_POS] & 0x0F) <<8) + (uint16_t)buf[AXS_TOUCH_ONE_POINT_LEN*point_index+AXS_TOUCH_X_L_POS])
#define AXS_GET_POINT_Y(buf,point_index) (((uint16_t)(buf[AXS_TOUCH_ONE_POINT_LEN*point_index+AXS_TOUCH_Y_H_POS] & 0x0F) <<8) + (uint16_t)buf[AXS_TOUCH_ONE_POINT_LEN*point_index+AXS_TOUCH_Y_L_POS])
#define AXS_GET_POINT_EVENT(buf,point_index) (buf[AXS_TOUCH_ONE_POINT_LEN*point_index+AXS_TOUCH_EVENT_POS] >> 6)

uint8_t read_touchpad_cmd[11] = {0xb5, 0xab, 0xa5, 0x5a, 0x0, 0x0, 0x0, 0x8};
void my_touchpad_read(lv_indev_t *indev_driver, lv_indev_data_t *data) {
    uint8_t buff[20] = {0};

    Wire.beginTransmission(0x3B);
    Wire.write(read_touchpad_cmd, 8);
    Wire.endTransmission();
    Wire.requestFrom(0x3B, 8);
    while (!Wire.available());
    Wire.readBytes(buff, 8);

    uint16_t pointX;
    uint16_t pointY;
    uint16_t type = 0;

    type = AXS_GET_GESTURE_TYPE(buff);
    pointX = AXS_GET_POINT_Y(buff,0);
    pointY = AXS_GET_POINT_X(buff,0);

    if (!type && (pointX || pointY)) {
        //pointX = (480-pointX);
        //pointY = (320-pointY);
        if(pointX > 480) pointX = 480;
        if(pointY > 320) pointY = 320;
        data->state = LV_INDEV_STATE_PR;
        data->point.x = pointY;
        data->point.y = pointX;

        //char buf[20] = {0};
        //sprintf(buf, "(%d, %d)", data->point.x, data->point.y);
        //f(ui_cartext != NULL)
        //lv_label_set_text(ui_cartext, buf);
    }
    else {
        data->state = LV_INDEV_STATE_REL;
    }
}





static uint16_t *buf;
static uint16_t *buf1;



void my_flush_cb(lv_display_t * disp,const lv_area_t * area, uint8_t * px_map)//但是传入驱动函数的颜色数据是一个16位的数组(根据设置的颜色深度有关)
{
    /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one
     *`put_px` is just an example, it needs to be implemented by you.*/
  //Serial.println("disp_sta\n");
  uint16_t * color_p = (uint16_t *)px_map;
  uint16_t  x = (uint16_t)(area->x1);
  uint16_t  y = (uint16_t)(area->y1);
  uint16_t  w = (uint16_t)(area->x2 - x +1);
  uint16_t  h = (uint16_t)(area->y2 - y +1);
  lv_draw_sw_rgb565_swap(color_p,(w-1)*(h-1));//将颜色顺序反转
  //Serial.println(x);
     lcd_PushColors(x, y, w, h, color_p);
     lv_disp_flush_ready(disp);
}









static uint8_t song_st = 1;//声音播放状态
String music_tt;
String music_tt1 = "407032014";
String music_tt2 = "";
String speak_tt ="";
String minimax_tt="";


//定时中断回调1ms执行一次
void flash(int tt) {  
  lv_tick_inc(1);//lvgl系统时间 1 ms 调用一次  停止心跳即暂停lvgl的运行
 
}




void lvgl_task(void *pt)
{
    while (1) {
        vTaskDelay(1);//在此任务延时函数
        lv_timer_handler();
    }
    vTaskDelete(NULL);
}

void audioTask(void *pt)
{   music_sd_init();
    audio.setAudioTaskCore(0);
    //uint8_t tt=0;
    while (1) {
        music_loop();
        if(song_st==0)audio.stopSong();  // stops task for audio
        //else audio.startAudioTask();
        vTaskDelay(2);
    }
    vTaskDelete(NULL);
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("sta\n");
   
   

   pinMode(TOUCH_RES, OUTPUT);
   digitalWrite(TOUCH_RES, HIGH);delay(2);
   digitalWrite(TOUCH_RES, LOW);delay(10);
   digitalWrite(TOUCH_RES, HIGH);delay(2);

    Wire.begin(TOUCH_IICSDA, TOUCH_IICSCL);


  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH);
 //lcd_setRotation(1);
  axs15231_init();
 



   size_t buffer_size =
        sizeof(uint16_t) * EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES;
  
    buf = (uint16_t *)ps_malloc(buffer_size);
    if (buf == NULL) {
      while (1) {
        Serial.println("buf NULL");
        delay(500);
      }
    }

    buf1 = (uint16_t *)ps_malloc(buffer_size);
    if (buf1 == NULL) {
      while (1) {
        Serial.println("buf NULL");
        delay(500);
      }
    }

 
  lv_init();//在所有lvgl相关函数之前调用

 
  lv_display_t * display = lv_display_create(320,480);
  lv_display_set_flush_cb(display, my_flush_cb);
  lv_display_set_buffers(display, buf, buf1, buffer_size, LV_DISPLAY_RENDER_MODE_FULL);
  //lv_draw_sw_rotate();//软件旋转
  //lv_display_set_rotation(display,LV_DISPLAY_ROTATION_0);//硬件支持旋转


  /*Register at least one display before you register any input devices*/
    lv_indev_t * indev_drv = lv_indev_create();
    lv_indev_set_type(indev_drv, LV_INDEV_TYPE_POINTER);   /*See below.*/
    lv_indev_set_read_cb(indev_drv, my_touchpad_read);  /*See below.*/

   
  


  /*Change the active screen's background color*/
    //lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x0000FF), LV_PART_MAIN);

   
     ui_init();
      // 配置周期性定时器
    timer.attach(0.001, flash, 1);//时间(秒)，回调，输入到回调函数的值    //使用中断回调函数1 ms 调用一次 告诉lvgl运行时间

   xTaskCreatePinnedToCore(lvgl_task, "lvgl_task", 1024 * 10, NULL, 2, NULL, 1);
   xTaskCreatePinnedToCore(audioTask, "audio_task", 1024 * 5, NULL, 2, NULL, 0);
  
  


  Serial.println("end\n");
 

}



void who_are_you(lv_event_t * e)
{
	// Your code here
  if(song_st==0){
  audio.connecttohost(minimax_get_audio(getGPTAnswer("你是谁呀？")).c_str());
  song_st=1;}
  else audio.connecttohost(minimax_get_audio(getGPTAnswer("你是谁呀？")).c_str());

}

void gu_shi66(lv_event_t * e)
{
	// Your code here
   if(song_st==0){
  audio.connecttohost(minimax_get_audio(getGPTAnswer("讲个故事给我听")).c_str());
  song_st=1;}
  else audio.connecttohost(minimax_get_audio(getGPTAnswer("讲个故事给我听")).c_str());
}

void what_time(lv_event_t * e)
{
	// Your code here
   if(song_st==0){
  audio.connecttohost(minimax_get_audio(getGPTAnswer("现在北京是什么时间？")).c_str());
  song_st=1;}
  else audio.connecttohost(minimax_get_audio(getGPTAnswer("现在北京是什么时间？")).c_str());
}

void what_weather(lv_event_t * e)
{
	// Your code here
   if(song_st==0){
  audio.connecttohost(minimax_get_audio(getGPTAnswer("今天天气怎么样？")).c_str());
  song_st=1;}
  else  audio.connecttohost(minimax_get_audio(getGPTAnswer("今天天气怎么样？")).c_str());
}

void send2minimax(lv_event_t * e)
{
	// Your code here
  speak_tt = lv_textarea_get_text(ui_TextArea1);//获取文本框输入的文本
  if(song_st==0){
  minimax_tt = getGPTAnswer(speak_tt);
  audio.connecttohost(minimax_get_audio(minimax_tt).c_str());
  _ui_label_set_property(ui_Label1,_UI_LABEL_PROPERTY_TEXT,minimax_tt.c_str());
  song_st=1;}
  else {minimax_tt = getGPTAnswer(speak_tt);
  audio.connecttohost(minimax_get_audio(minimax_tt).c_str());
  _ui_label_set_property(ui_Label1,_UI_LABEL_PROPERTY_TEXT,minimax_tt.c_str());}
  
}


void send_music(lv_event_t * e)
{
	// Your code here
  music_tt = lv_textarea_get_text(ui_TextArea2);//获取文本框输入的文本
  music_tt1 = music_tt;
  music_tt2 = "http://music.163.com/song/media/outer/url?id="+music_tt1+".mp3";
  if(song_st==0){
  audio.connecttohost(music_tt2.c_str());song_st=1;}
  else audio.connecttohost(music_tt2.c_str());

}

void loop() {
 vTaskDelay(1000);   

}

